#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_ttf.h>
#include <allegro5/mouse.h>

#include <iostream>
#include <time.h>
#include <math.h>

#include "objects.h"
#include "gui.h"
#include "highscores.h"

bool keys[] = {false, false, false, false, false, false};
enum KEYS{UP, DOWN, LEFT, RIGHT, SPACE, ESCAPE};

enum STATE{MENU, PLAYING, GAMEOVER, HOWTOPLAY, INSERTHIGHSCORE, HIGHSCORELIST, ABOUTGAME};

float speed = 0;
void ChangeState(int &state, int newState, Player &player, Bullet bullet[],Mouse &mouse, Evilrobots evilrobots[],Frisbee frisbee[], Powerups power[]);

int main(int argc, char **argv)
{
        //==============================================
        //SHELL VARIABLES
        //==============================================
        bool done = false;
        bool render = false;

        float gameTime = 0;
        int frames = 0;
        int gameFPS = 0;

        //==============================================
        //PROJECT VARIABLES
        //==============================================
        int state = -1;
		bool check = false;
		char initials[3] = {'-','-'};
		initials[0] = '-';
		char cha = ' ';
		bool textinput = false;
		char unichar;
		int name = 0;
		bool enterkey = false;
		bool backspace = false;
        Player player;
        Bullet bullet[MAX_BULLETS];
        Mouse mouse;
        Evilrobots evilrobots[100];
        Button buttons[10];
        Frisbee frisbee[5];
		Scores scores[10];
		Powerups power[5];

		ALLEGRO_BITMAP *tutorialt;
		ALLEGRO_BITMAP *AmmoPowUp;
		ALLEGRO_BITMAP *HealthPowUp;
		ALLEGRO_BITMAP *InvincPowUp;
		ALLEGRO_BITMAP *Map;
		ALLEGRO_BITMAP *Goodplayer;
		ALLEGRO_BITMAP *Badplayer;
        //==============================================
        //ALLEGRO VARIABLES
        //==============================================
        ALLEGRO_DISPLAY *display = NULL;
        ALLEGRO_EVENT_QUEUE *event_queue = NULL;
        ALLEGRO_TIMER *timer;
        ALLEGRO_FONT *font18;
        ALLEGRO_FONT *font32;
        
        //==============================================
        //ALLEGRO INIT FUNCTIONS
        //==============================================
        if(!al_init())                                                                          //initialize Allegro
                return -1;

       al_set_new_display_flags(ALLEGRO_FULLSCREEN);

        display = al_create_display(WIDTH, HEIGHT);                     //create our display object

        if(!display)                                                                            //test display object
                return -1;

        //==============================================
        //ADDON INSTALL
        //==============================================
        al_install_keyboard();
        al_install_mouse();
        al_init_image_addon();
        al_init_font_addon();
        al_init_ttf_addon();
        al_init_primitives_addon();


        //==============================================
        //PROJECT INIT
        //==============================================
		srand (time(NULL));
        font18 = al_load_font("arial.ttf", 18, 0);
        font32 = al_load_font("arial.ttf", 32, 0);

		tutorialt = al_load_bitmap("tutorial.png");

		AmmoPowUp = al_load_bitmap("PowerUps/AmmoPowup.png");
		HealthPowUp = al_load_bitmap("PowerUps/HealthPowUp.png");
		InvincPowUp = al_load_bitmap("PowerUps/InviciPowUp.png");
		Goodplayer = al_load_bitmap("yellowgoodrobot.png");
		Badplayer = al_load_bitmap("evilrobot.png");

		al_convert_mask_to_alpha(AmmoPowUp, al_map_rgb(255,0,255));
		al_convert_mask_to_alpha(HealthPowUp, al_map_rgb(255,0,255));
		al_convert_mask_to_alpha(InvincPowUp, al_map_rgb(255,0,255));
		al_convert_mask_to_alpha(Goodplayer, al_map_rgb(255,0,255));
		al_convert_mask_to_alpha(Badplayer, al_map_rgb(255,0,255));

		Map = al_load_bitmap("Map.png");

        ChangeState(state, MENU, player, bullet,mouse, evilrobots,frisbee,power);
		initbuttons(buttons);

        playerinit(player);
        bulletinit(bullet);
        initmouse(mouse);
        initevilrobots(evilrobots);
        frisbeeinit(frisbee);
        createevilrobots(evilrobots, player);
		initpowerups(power);

		loadscores(scores);
        
        //CREATE THE BUTTONS!!!
        createbuttons(buttons, 150, 150, 200, 75, "PLAY", PLAY);
		createbuttons(buttons, 150, 250, 200, 75, "HIGHSCORES", HIGHSCORES);
		createbuttons(buttons, 150, 350, 200,75, "TUTORIAL", HOWTO);
		createbuttons(buttons, 150, 450, 200, 75, "ABOUT", ABOUT);
        createbuttons(buttons, 150, 550, 200, 75, "QUIT", QUIT);

        //==============================================
        //TIMER INIT AND STARTUP
        //==============================================
        event_queue = al_create_event_queue();
        timer = al_create_timer(1.0 / 500+speed);

        al_register_event_source(event_queue, al_get_timer_event_source(timer));
        al_register_event_source(event_queue, al_get_keyboard_event_source());
        al_register_event_source(event_queue, al_get_mouse_event_source());

        al_start_timer(timer);
        gameTime = al_current_time();
        while(!done)
        {
                ALLEGRO_EVENT ev;
                al_wait_for_event(event_queue, &ev);

                //==============================================
                //INPUT
                //==============================================
                if(ev.type == ALLEGRO_EVENT_MOUSE_AXES || ev.type == ALLEGRO_EVENT_MOUSE_ENTER_DISPLAY)
                {
                        mouse.x = ev.mouse.x;
                        mouse.y = ev.mouse.y;
                }
                else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN)
                {
                                        if(ev.mouse.button & 1)
                        mouse.rightclick = true;
                                        if(ev.mouse.button & 2)
                                                mouse.leftclick = true;
                }
                else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP)
                {
					if(ev.mouse.button & 1)
                        mouse.rightclick = false;
					if(ev.mouse.button & 2)
						mouse.leftclick = false;
                }
                else if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
                {
						switch(ev.keyboard.keycode)
                        {
                        case ALLEGRO_KEY_ESCAPE:
                                keys[ESCAPE] = true;
                                break;
                        case ALLEGRO_KEY_A:
                                keys[LEFT] = true;
                                break;
                        case ALLEGRO_KEY_D:
                                keys[RIGHT] = true;
                                break;
                        case ALLEGRO_KEY_W:
                                keys[UP] = true;
                                break;
                        case ALLEGRO_KEY_S:
                                keys[DOWN] = true;
                                break;
                        case ALLEGRO_KEY_SPACE:
                                keys[SPACE] = true;
                                break;
						case ALLEGRO_KEY_ENTER:
								enterkey = true;
								break;
						case ALLEGRO_KEY_BACKSPACE:
								backspace = true;
								break;								
						}
                }
				else if(ev.type == ALLEGRO_EVENT_KEY_CHAR)
				{
					if(state == INSERTHIGHSCORE)
					{
						switch(ALLEGRO_EVENT_KEY_CHAR)
						{
							case ALLEGRO_EVENT_KEY_CHAR:
								unichar = ev.keyboard.unichar;
								textinput = true;
								break;
						}
					}
				}
                else if(ev.type == ALLEGRO_EVENT_KEY_UP)
                {
                        switch(ev.keyboard.keycode)
                        {
                        case ALLEGRO_KEY_ESCAPE:
                                keys[ESCAPE] = false;
                                break;
                        case ALLEGRO_KEY_A:
                                keys[LEFT] = false;
                                break;
                        case ALLEGRO_KEY_D:
                                keys[RIGHT] = false;
                                break;
                        case ALLEGRO_KEY_W:
                                keys[UP] = false;
                                break;
                        case ALLEGRO_KEY_S:
                                keys[DOWN] = false;
                                break;
                        case ALLEGRO_KEY_SPACE:
                                keys[SPACE] = false;
                                break;
						case ALLEGRO_KEY_ENTER:
								enterkey = false;
								break;
						case ALLEGRO_KEY_BACKSPACE:
								backspace = true;
								break;
                        }
                }
                //==============================================
                //GAME UPDATE
                //==============================================
                else if(ev.type == ALLEGRO_EVENT_TIMER)
                {
                        render = true;

                        //UPDATE FPS===========
                        frames++;
                        if(al_current_time() - gameTime >= 1)
                        {
                                gameTime = al_current_time();
                                gameFPS = frames;
                                frames = 0;
                        }
                        //=====================

                        if(state == MENU)
                        {
                                if(checkforbuttonpress(buttons, mouse) == PLAY && mouse.rightclick != 0)
                                {
									ChangeState(state,PLAYING, player, bullet,mouse, evilrobots,frisbee,power);
                                }
                                if(checkforbuttonpress(buttons, mouse) == QUIT && mouse.rightclick != 0)
                                {
									done = true;
                                }
                                if(checkforbuttonpress(buttons, mouse) == HOWTO && mouse.rightclick != 0)
                                {
									ChangeState(state,HOWTOPLAY, player, bullet,mouse, evilrobots,frisbee,power);
                                }
                                if(checkforbuttonpress(buttons, mouse) == HIGHSCORES && mouse.rightclick != 0)
                                {
									ChangeState(state,HIGHSCORELIST, player, bullet,mouse, evilrobots,frisbee,power);
                                }
                                if(checkforbuttonpress(buttons, mouse) == ABOUT && mouse.rightclick != 0)
                                {
									ChangeState(state,ABOUTGAME, player, bullet,mouse, evilrobots,frisbee,power);
                                }
                        }
                        else if(state == PLAYING)
                        {
							speed = speed + 0.0001; 
								check = true;
                                //input///////////////////////
                                if(keys[UP])
									playermove(player,0,-1);
                                if(keys[LEFT])
									playermove(player,-1,0);
                                if(keys[RIGHT])
									playermove(player,1,0);
                                if(keys[DOWN])
									playermove(player,0,1);
                                if(keys[ESCAPE])
									ChangeState(state,MENU, player, bullet,mouse, evilrobots,frisbee,power);
								//Game Update//to be put in functions///////////////
								player.gundelay++;
								if(player.gundelay > player.setdelay)
									player.gundelay = 0;

								if(mouse.rightclick && player.gundelay > player.setdelay - 1 && player.gunheat < 50)
								{
									createbullet(bullet, player, mouse);
									player.gunheat++;
								}
								if(mouse.rightclick == false && player.gunheat > 0 && player.gundelay > player.setdelay - 2)
									player.gunheat--;

								if(player.health <= 0)
									ChangeState(state, GAMEOVER, player, bullet,mouse, evilrobots,frisbee,power);

                                //Game update/////////////////
								powerupdate(player);
								frisbeeupdate(frisbee);
                                bulletupdate(bullet);
                                updateevilrobots(evilrobots, player);
                                if(rand() % 1000 < 2)
									frisbeecreate(frisbee);
								if(rand() % 1000 < 2)
									createevilrobots(evilrobots, player);
								if(rand() % 10000 < 2)
									powerupscreate(power);

								if(player.x > 1024-20)
									player.x = 1024-20;
								if(player.x < 0+20)
									player.x = 0+20;
								if(player.y < 0+20)
									player.y = 0+20;
								if(player.y > 768-20)
									player.y = 768-20;
                                //Collision//////////////////
								PowerupandPlayer(player, power);
								EvilrobotsandEvilrobots(evilrobots, evilrobots);
                                BulletandEvilrobots(bullet,evilrobots, player);
                                FrisbeeandPlayer(player,frisbee);
								PlayerandEvilrobots(evilrobots,player);
                        }
						else if(state == HOWTOPLAY)
						{
                                if(keys[ESCAPE])
									ChangeState(state, MENU, player, bullet,mouse, evilrobots,frisbee,power);
						}
                        else if(state == GAMEOVER)
                        {
							initials[0] = '-';
							initials[1] = '-';
							initials[2] = '-';
							name = 0;
							int place = checkplacement(player,scores);

							if(place < 9 && check == true)
							{
								ChangeState(state, INSERTHIGHSCORE, player, bullet,mouse, evilrobots,frisbee,power);
								check = false;
							}
							
                            if(keys[ESCAPE])
								ChangeState(state, MENU, player, bullet,mouse, evilrobots,frisbee,power);
                        }
						else if(state == INSERTHIGHSCORE)
						{
							if(backspace == true && name >= 1)
							{
								name--;
								initials[name] = '-';
								al_rest(0.1);
								backspace = false;
							}
							if(textinput)
							{
								if(name <= 2)
								{
									initials[name] = unichar;
									name++;
									textinput = false;
								}
							}
							if(enterkey)
							{
								int place = checkplacement(player,scores);
								movedownplayers(scores,player.score,place,initials, player);
								savescores(scores);
								ChangeState(state,MENU,player,bullet,mouse,evilrobots,frisbee,power);
							}
						}
						else if(state == HIGHSCORELIST)
						{
                                if(keys[ESCAPE])
									ChangeState(state, MENU, player, bullet,mouse, evilrobots,frisbee,power);
						}
						else if(state == ABOUTGAME)
						{
                                if(keys[ESCAPE])
									ChangeState(state, MENU, player, bullet,mouse, evilrobots,frisbee,power);
						}
                }

                //==============================================
                //RENDER
                //==============================================
                if(render && al_is_event_queue_empty(event_queue))
                {
                        render = false;

                        //BEGIN PROJECT RENDER================
                        if(state == MENU)
                        {
                                al_draw_text(font32,al_map_rgb(0,0,200),WIDTH/2+20,HEIGHT/2-100,ALLEGRO_ALIGN_CENTER,"Robot Defender");
                                drawbuttons(buttons, font18);
                        }
                        else if(state == PLAYING)
                        {
							//Map//////////////////////////
							al_draw_bitmap(Map,0,0,NULL);
                            //Game Objects////////////////
							powerupdraw(power,AmmoPowUp,InvincPowUp,HealthPowUp);
                            frisbeedraw(frisbee);
                            bulletdraw(bullet);
                            playerdraw(player, Goodplayer);
                            drawevilrobots(evilrobots, Badplayer);

							//HUD/////////////////
							al_draw_textf(font32,al_map_rgb(200,100,100),HEIGHT+40,WIDTH/2,ALLEGRO_ALIGN_CENTER,"Points: %i", player.score);
							drawpowerupnote(font32, player);
							//Health
							al_draw_line(player.x-25,player.y-40,(player.x+50)-25,(player.y)-40,al_map_rgb(30,30,30),5);
							al_draw_line(player.x-25,player.y-40,(player.x+player.health)-25,(player.y)-40,al_map_rgb(200,10,10),5);
							//Power
							al_draw_line(player.x-25,player.y-25,(player.x+50)-25,(player.y)-25,al_map_rgb(30,30,30),5);
							al_draw_line(player.x-25,player.y-25,(player.x-player.gunheat+50)-25,(player.y)-25,al_map_rgb(10,10,200),5);
							if(player.score > 100 && player.score < 150)
									al_draw_text(font18,al_map_rgb(0,0,0),100,100,0,"Clue:Go salute our countries Heroes and prove that our flag is still there.");
                        }
						else if(state == HOWTOPLAY)
						{
							al_draw_bitmap(tutorialt,0,0,0);
						}
                        else if(state == GAMEOVER)
                        {
                                al_draw_text(font32, al_map_rgb(255, 255, 255), WIDTH / 2, HEIGHT / 2, ALLEGRO_ALIGN_CENTRE, "You lost!");
								al_draw_textf(font32, al_map_rgb(255, 255, 255), WIDTH / 2, HEIGHT / 2+30, ALLEGRO_ALIGN_CENTRE, "Score: %i", player.score);
								al_draw_textf(font32, al_map_rgb(255, 255, 255), WIDTH / 2, HEIGHT / 2+60, ALLEGRO_ALIGN_CENTRE, "Press Escape to continue");
                        }
						else if(state == INSERTHIGHSCORE)
						{
								al_draw_text(font18,al_map_rgb(200,100,100),WIDTH/2,100,ALLEGRO_ALIGN_CENTER,"You got a new high score!");
								al_draw_text(font18,al_map_rgb(200,100,100),WIDTH/2,130,ALLEGRO_ALIGN_CENTER,"Insert initials:");
								al_draw_text(font18,al_map_rgb(255, 255, 255), WIDTH / 2, HEIGHT / 2, ALLEGRO_ALIGN_CENTRE,initials);
								al_draw_textf(font18,al_map_rgb(255, 255, 255), 30, 10, NULL, "%i", name);
						}
						else if(state == HIGHSCORELIST)
						{
								drawscores(scores, font32);
						}
						else if(state == ABOUTGAME)
						{
							al_draw_text(font18,al_map_rgb(255,255,255),WIDTH/2,HEIGHT/2-20,ALLEGRO_ALIGN_CENTER,"Written by William Mace for the Torc Team 2137 the Oxford High School robotics team using C++ and Allegro 5");
							al_draw_text(font32,al_map_rgb(255,255,255),WIDTH/2,HEIGHT/2,ALLEGRO_ALIGN_CENTER,"http://code.google.com/p/teamtorc-robotics-game/");
							al_draw_text(font32,al_map_rgb(255,255,255),WIDTH/2,HEIGHT/2+40,ALLEGRO_ALIGN_CENTER,"http://www.torc2137.com/");
						}
                        //FLIP BUFFERS========================
                        al_flip_display();
                        al_clear_to_color(al_map_rgb(0,0,0));
                }
        }
		savescores(scores);
        //==============================================
        //DESTROY PROJECT OBJECTS
        //==============================================
		al_destroy_bitmap(tutorialt);
		al_destroy_bitmap(AmmoPowUp);
		al_destroy_bitmap(HealthPowUp);
		al_destroy_bitmap(InvincPowUp);
		al_destroy_bitmap(Map);
        //SHELL OBJECTS=================================
        al_destroy_font(font18);
		al_destroy_font(font32);
        al_destroy_timer(timer);
        al_destroy_event_queue(event_queue);
        al_destroy_display(display);

        return 0;
}

void ChangeState(int &state, int newState, Player &player, Bullet bullet[],Mouse &mouse, Evilrobots evilrobots[],Frisbee frisbee[], Powerups power[])
{
	speed = 0;
        if(state == MENU)
        {

        }
        else if(state == PLAYING)
        {
        }
        else if(state == GAMEOVER)
        {
			
        }
		else if(state == HOWTOPLAY)
		{

		}

        state = newState;

        if(state == MENU)
        {
        }
        else if(state == PLAYING)
        {
			playerinit(player);
			bulletinit(bullet);
			initmouse(mouse);
			initevilrobots(evilrobots);
			frisbeeinit(frisbee);
			createevilrobots(evilrobots, player);
			initpowerups(power);
        }
        else if(state == GAMEOVER)
        {

        }
		else if(state == HOWTOPLAY)
		{

		}
}